﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Configuration;
using System.Messaging;

namespace CometTester
{
    public partial class MainForm : Form
    {

        private int _numOfConnections = 0;
        private int _totalUsers = 0;
        private string _message;

        public MainForm()
        {
            InitializeComponent();
        }

        private void _executeLoadTestButton_Click(object sender, EventArgs e)
        {
            int maxUsers = Convert.ToInt32(_maxUserLoad.Text);
            int repsPerSet = Convert.ToInt32(_repsPerLoadSet.Text);
            int bytesPerMsg = Convert.ToInt32(_bytesPerMessage.Text);
            int waitTime = Convert.ToInt32(_waitTime.Text);

            StringBuilder msgBuilder = new StringBuilder();
            for (int i = 0; i < bytesPerMsg; i++)
            {
                msgBuilder.Append("A");
            }

            LoadTestComet(maxUsers, repsPerSet, msgBuilder.ToString(), waitTime);
        }

        public void LoadTestComet(int maxNumberOfUsers, int repsPerSet, string message, int waitTime)
        {
            if (maxNumberOfUsers <= 0 || repsPerSet <= 0)
            {
                return;
            }

            ManualResetEvent[] doneEvents = new ManualResetEvent[maxNumberOfUsers];
            CometTester[] cometTester = new CometTester[maxNumberOfUsers];

            for (int numOfUsers = 0; numOfUsers < maxNumberOfUsers; numOfUsers ++)
            {
                doneEvents[numOfUsers] = new ManualResetEvent(false);
                CometTester t = new CometTester(numOfUsers, doneEvents[numOfUsers], message, repsPerSet, waitTime);
                cometTester[numOfUsers] = t;
                ThreadPool.QueueUserWorkItem(t.EngageCometBroadcast, numOfUsers);

            }

            //WaitHandle.WaitAll(doneEvents);
            foreach (ManualResetEvent resetEvent in doneEvents)
            {
                resetEvent.WaitOne();
            }
            
            double totalTime = 0;
            int numberOfFailures = 0;
            int numberOfWcfFailures = 0;

            for (int i = 0; i < maxNumberOfUsers; i++)
            {
                CometTester t = cometTester[i];
                totalTime += t.TestResults.TimeTakenInMilliseconds;
                numberOfFailures += t.TestResults.RepsFailed;
                numberOfWcfFailures += t.TestResults.WcfFailures;

            }

            double averageResponseTime = totalTime / maxNumberOfUsers;

            MessageBox.Show("The average Comet response time was " + averageResponseTime + " ms.  Number of failures: " + numberOfFailures + ".  Number of WCF failures: " + numberOfWcfFailures);
        }

        private void _pingLoadTestButton_Click(object sender, EventArgs e)
        {
            int maxUsers = Convert.ToInt32(_maxUserLoad.Text);
            int repsPerSet = Convert.ToInt32(_repsPerLoadSet.Text);
            //int bytesPerMsg = Convert.ToInt32(_bytesPerMessage.Text);
            int waitTime = Convert.ToInt32(_waitTime.Text);

            PingComet(maxUsers, repsPerSet, "PING", waitTime);
        }

        public void PingComet(int maxNumberOfUsers, int repsPerSet, string message, int waitTime)
        {
            if (maxNumberOfUsers <= 0 || repsPerSet <= 0)
            {
                return;
            }

            ManualResetEvent[] doneEvents = new ManualResetEvent[maxNumberOfUsers];
            CometTester[] cometTester = new CometTester[maxNumberOfUsers];

            for (int numOfUsers = 0; numOfUsers < maxNumberOfUsers; numOfUsers++)
            {
                doneEvents[numOfUsers] = new ManualResetEvent(false);
                CometTester t = new CometTester(numOfUsers, doneEvents[numOfUsers], message, repsPerSet, waitTime);
                cometTester[numOfUsers] = t;
                ThreadPool.QueueUserWorkItem(t.PingComet, numOfUsers);

            }

            //WaitHandle.WaitAll(doneEvents);
            foreach (ManualResetEvent resetEvent in doneEvents)
            {
                resetEvent.WaitOne();
            }

            double totalTime = 0;
            int numberOfFailures = 0;
            int numberOfWcfFailures = 0;

            for (int i = 0; i < maxNumberOfUsers; i++)
            {
                CometTester t = cometTester[i];
                totalTime += t.TestResults.TimeTakenInMilliseconds;
                numberOfFailures += t.TestResults.RepsFailed;
                numberOfWcfFailures += t.TestResults.WcfFailures;

            }

            double averageResponseTime = totalTime / maxNumberOfUsers;

            MessageBox.Show("The average Comet response time was " + averageResponseTime + " ms.  Number of failures: " + numberOfFailures + ".  Number of WCF failures: " + numberOfWcfFailures);
        }

        private void _broadcastTestButton_Click(object sender, EventArgs e)
        {
            int maxUsers = Convert.ToInt32(_maxUserLoad.Text);
            _totalUsers = maxUsers;
            int repsPerSet = Convert.ToInt32(_repsPerLoadSet.Text);
            int bytesPerMsg = Convert.ToInt32(_bytesPerMessage.Text);
            int waitTime = Convert.ToInt32(_waitTime.Text);
            int messageSendFrequency = Convert.ToInt32(_messageSendFrequency.Text);

            StringBuilder messageBuilder = new StringBuilder();

            for (int i = 0; i < bytesPerMsg; i++)
            {
                messageBuilder.Append("B");
            }

            _message = messageBuilder.ToString();

            _messagePumpTimer.Interval = messageSendFrequency;
            _messagePumpTimer.Tick += new EventHandler(_messagePumpTimer_Tick);
            _messagePumpTimer.Start();

            broadcastTestComet(maxUsers, repsPerSet, messageBuilder.ToString(), waitTime);

        }

        public void broadcastTestComet(int maxNumberOfUsers, int repsPerSet, string message, int waitTime)
        {
            if (maxNumberOfUsers <= 0 || repsPerSet <= 0)
            {
                return;
            }

            ManualResetEvent[] doneEvents = new ManualResetEvent[maxNumberOfUsers];
            CometTester[] cometTester = new CometTester[maxNumberOfUsers];

            for (int numOfUsers = 0; numOfUsers < maxNumberOfUsers; numOfUsers++)
            {
                doneEvents[numOfUsers] = new ManualResetEvent(false);
                CometTester t = new CometTester(numOfUsers, doneEvents[numOfUsers], message, repsPerSet, waitTime);
                t.CometConnectionEvent += new EventHandler<CometConnectionEventArgs>(connectedToComet);
                cometTester[numOfUsers] = t;
                ThreadPool.QueueUserWorkItem(t.AsyncTest, numOfUsers);

            }

            //ManualResetEvent sendMessageResetEvent = new ManualResetEvent(false);
            //CometTester t1 = new CometTester(1, sendMessageResetEvent, message, repsPerSet, waitTime);
            //ThreadPool.QueueUserWorkItem(t1.DumpMessage, maxNumberOfUsers);

            //Dump message to message queue:
            

            //WaitHandle.WaitAll(doneEvents);
            foreach (ManualResetEvent resetEvent in doneEvents)
            {
                resetEvent.WaitOne();
            }

            //sendMessageResetEvent.WaitOne();
            _messagePumpTimer.Stop();

            double totalTime = 0;
            int numberOfFailures = 0;
            int numberOfWcfFailures = 0;

            for (int i = 0; i < maxNumberOfUsers; i++)
            {
                CometTester t = cometTester[i];
                totalTime += t.TestResults.TimeTakenInMilliseconds;
                numberOfFailures += t.TestResults.RepsFailed;
                numberOfWcfFailures += t.TestResults.WcfFailures;

            }

            double averageResponseTime = totalTime / (maxNumberOfUsers * repsPerSet - numberOfFailures);

            MessageBox.Show("The average Comet response time was " + averageResponseTime + " ms.  Number of failures: " + numberOfFailures + ".  Number of WCF failures: " + numberOfWcfFailures);
        }

        private void connectedToComet(object sender, CometConnectionEventArgs args)
        {
            _numOfConnections++;
            if (_numOfConnections > _totalUsers)
            {
                sendMessage();
            }
        }

        private void sendMessage()
        {
            //Dump message to message queue:
            try
            {
                //_cometServer.BroadcastMessage(_sendCometMsgTextBox.Text);
                string msgQueueName = ConfigurationManager.AppSettings["CometQueue"];
                MessageQueue testMessageQueue = new MessageQueue(msgQueueName);
                System.Messaging.Message msg = new System.Messaging.Message(_message, new XmlMessageFormatter(new Type[] { typeof(string) }));
                msg.Body = _message;
                testMessageQueue.Send(msg);
            }
            catch (Exception ex)
            {
                string error = ex.ToString();
                //Response.Write(error);
                throw ex;
            }
        }

        private void _messagePumpTimer_Tick(object sender, EventArgs e)
        {
            try
            {
                //_cometServer.BroadcastMessage(_sendCometMsgTextBox.Text);
                string msgQueueName = ConfigurationManager.AppSettings["CometQueue"];
                MessageQueue cometMessageQueue = new MessageQueue(msgQueueName);
                System.Messaging.Message msg = new System.Messaging.Message(_message, new XmlMessageFormatter(new Type[] { typeof(string) }));
                cometMessageQueue.Send(msg);
            }
            catch (Exception ex)
            {
                string error = ex.ToString();
                //Response.Write(error);
                MessageBox.Show(error, "Comet Message Pump Error");
            }
        }


    }
}

